package org.benetech.util;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;

/**
 * Given a set of collections, be prepared to sort them in order according to their deviance from the mean size. That
 * is, the collection with the most average size will be returned first, and the collection with the least average size
 * will be returned last.
 * @author Reuben Firmin
 * @param <T> the type of collections being sorted; generic Collection is fine if necessary
 */
public final class SizeDevianceFromMeanComparator<T extends Collection> implements Comparator, Serializable {

	private double average;

	/**
	 * Default constructor.
	 */
	public SizeDevianceFromMeanComparator() {
	}

	/**
	 * Set the average size that the collection sizes should be sorted relative to.
	 * @param average positive double
	 */
	public void setAverage(final double average) {
		this.average = average;
	}

	/**
	 * Convenience method to run the sort. Alternative is to call {@link #setAverage} prior to invoking this comparator.
	 * @param collections never null
	 * @return never null
	 */
	public List<T> sort(final T... collections) {
		int sum = 0;
		for (T collection : collections) {
			sum += collection.size();
		}
		this.average = ((double) sum / collections.length);

		Arrays.sort(collections, this);
		return Arrays.asList(collections);
	}

	/**
	 * {@inheritDoc}
	 */
	public int compare(final Object o1, final Object o2) {
		final T coll1 = (T) o1;
		final T coll2 = (T) o2;

		final double coll1Distance = Math.abs(coll1.size() - average);
		final double coll2Distance = Math.abs(coll2.size() - average);

		if (coll1Distance > coll2Distance) {
			return 1;
		} else if (coll1Distance < coll2Distance) {
			return -1;
		}
		return 0;
	}

}
